package ldh.im.fxgui.component;

import javafx.beans.InvalidationListener;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.ListChangeListener;
import javafx.concurrent.Worker;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.web.PopupFeatures;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.util.Callback;
import ldh.im.dto.enmus.MessageType;
import ldh.im.fxbase.controller.ImagePageController;
import ldh.im.fxbase.util.RegionUtil;
import ldh.im.fxbase.richtext.*;
import ldh.im.fxbase.pojo.DbMessage;
import ldh.im.fxbase.service.AudioService;
import ldh.im.fxgui.util.UiUtil;
import org.kordamp.ikonli.fontawesome.FontAwesome;
import org.kordamp.ikonli.javafx.FontIcon;

import java.io.File;
import java.text.NumberFormat;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

public class UserMessagePane extends GridPane {

    private ImageView userHeadImageView = new ImageView();
    private Label userNameLabel = new Label();
//    private Text userMessageTextArea = new Text();
//    private WebView userMessageWebView = new WebView();
    private Node contentPane;
//    private HTMLEditor userMessageWebView = HtmlEditorUtil.createHtmlEditor();
//    private StackPane stackPane = new StackPane();
    private volatile AtomicBoolean isLoad = new AtomicBoolean(false);

    public UserMessagePane(DbMessage message) {
        contentPane = createNode(message);
        this.getStyleClass().add("message-list-pane");
        this.setPrefWidth(300);
//        this.setPrefHeight(60);
        this.setMaxWidth(400);
        this.setHgap(10);
        this.setMouseTransparent(false);
        userHeadImageView.setFitHeight(60);
        userHeadImageView.setFitWidth(60);
        userNameLabel.setStyle("-fx-font-size: 14px; -fx-padding: 0 1 0 0");

        this.focusedProperty().addListener(e->this.requestLayout());

//        userMessageWebView.setPrefHeight(20);
//        userMessageTextArea.setStyle("-fx-background-color: gray");
//        stackPane.getChildren().add(userMessageTextArea);
//        stackPane.getStyleClass().add("message-box");

        GridPane.setConstraints(userHeadImageView, 0, 0, 1, 2);
        GridPane.setConstraints(userNameLabel, 1, 0, 1, 1);
        GridPane.setConstraints(contentPane, 1, 1, 1, 1);

        ColumnConstraints c1 = new ColumnConstraints(60);
        ColumnConstraints c2 = new ColumnConstraints();
        c2.setHgrow(Priority.ALWAYS);

        RowConstraints r1 = new RowConstraints();
        r1.setValignment(VPos.TOP);
        RowConstraints r2 = new RowConstraints();

        this.getChildren().addAll(userHeadImageView, userNameLabel, contentPane);
        this.getColumnConstraints().addAll(c1, c2);
        this.getRowConstraints().addAll(r1, r2);

        this.setOnMouseDragged(e->e.consume());
        this.setOnDragDetected(e->e.consume());

        setData(message);
    }

    private void setData(DbMessage message) {
        userNameLabel.setText(message.getImGroup().getName());
//        userMessageWebView.getEngine().loadContent(message.getContent());
//            userMessageWebView.setHtmlText(textMessage.getMessage());
        if (message instanceof DbMessage) {
            DbMessage textMessage = (DbMessage) message;
            if (textMessage.getFromUser() != null) {
                Image image = new Image(textMessage.getFromUser().getHeadImg());
                userHeadImageView.setImage(image);
            }
        }

    }

    private Node createNode(DbMessage message) {
        if (message.getMessageType() == MessageType.Text) {
            ImText imText = new ImText();
            imText.setImContent(message.getContent());
            imText.setMaxWidth(300);
            imText.setPrefWidth(300);
            imText.getText().setWrappingWidth(300);
            return new Group(imText);
        } else if (message.getMessageType() == MessageType.Image) {
            ImTextPane textFlow = UiUtil.createImTextFlow(ImageTextItem.format(message.getContent()));
            textFlow.setPrefWidth(300);
            textFlow.setMaxWidth(300);
            textFlow.setMinWidth(300);
            return  new Group(textFlow);
        } else if (message.getMessageType() == MessageType.Web) {
            WebView webView = new WebView();
            webView.getEngine().load(message.getContent());
            bindEventWebView(webView);
            return webView;
        } else if (message.getMessageType() == MessageType.Html) {
            WebView webView = new WebView();
            webView.getEngine().loadContent(message.getContent());
            bindEventWebView(webView);
            return webView;
        } else if (message.getMessageType() == MessageType.RichText) {
            ImTextPane textFlow = UiUtil.createImTextFlow(message.getContent());
            textFlow.setPrefWidth(300);
            textFlow.setMaxWidth(300);
            textFlow.setMinWidth(300);
            return  new Group(textFlow);
        } else if (message.getMessageType() == MessageType.Audio) {
            StackPane anchorPane = new StackPane();
            anchorPane.setAlignment(Pos.CENTER_LEFT);
            anchorPane.getStyleClass().add("im-text-pane");

            NumberFormat numberFormat = NumberFormat.getNumberInstance();
            numberFormat.setMaximumFractionDigits(2);
            String text = numberFormat.format((double)message.getMessageExt().getSize()/1000) + " 秒";
            Label audioLabel = new Label(text);
            FontIcon fontIcon = FontIcon.of(FontAwesome.findByDescription("fa-file-sound-o"), 20, Color.GREEN);
            audioLabel.setGraphic(fontIcon);
            audioLabel.setOnMouseClicked(e->{
                if (audioLabel.getUserData() != null && audioLabel.getUserData().toString().equals("playing")) return;
                audioLabel.setUserData("playing");
                AudioService audioService = new AudioService(System.getProperty("user.dir") + "/data/audio");
                audioService.playRecord(message.getMessageExt().getLocalDir() + File.separator + message.getContent(), (Void)->{
                    audioLabel.setUserData("end!");
                });
            });
            anchorPane.getChildren().add(audioLabel);
            return anchorPane;
        } else if (message.getMessageType() == MessageType.File) {
            StackPane anchorPane = new StackPane();
            anchorPane.setAlignment(Pos.CENTER_LEFT);
            anchorPane.getStyleClass().add("im-text-pane");
            Label fileLabel = new Label(message.getContent());
            FontIcon fontIcon = FontIcon.of(FontAwesome.findByDescription("fa-file"), 20, Color.GREEN);
            fileLabel.setGraphic(fontIcon);
            fileLabel.setOnMouseClicked(e->{
                // todo 下载
            });
            anchorPane.getChildren().add(fileLabel);
            return anchorPane;
        }
        return new Label("");
    }

    private void bindEventWebView(WebView webView) {
        webView.getChildrenUnmodifiable().addListener(new ListChangeListener<Node>() {
            @Override public void onChanged(Change<? extends Node> change) {
                Set<Node> deadSeaScrolls = webView.lookupAll(".scroll-bar");
                for (Node scroll : deadSeaScrolls) {
                    scroll.setVisible(false);
                }
            }
        });


        webView.getEngine().getLoadWorker().stateProperty().addListener(
                new ChangeListener<Worker.State>() {
                    @Override
                    public void changed(ObservableValue<? extends Worker.State> ov, Worker.State oldState, Worker.State newState) {
                        if (newState == Worker.State.SUCCEEDED) {
                            if (isLoad.get()) return;
                            String js = "Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);";
                            Object dd = webView.getEngine().executeScript(js);
                            if (dd == null) return;
                            double d = Double.parseDouble(dd.toString());
                            if (d == 60.0d) d = 40d;
                            webView.setPrefHeight(d);
                            webView.setMinHeight(d);
                            webView.setMaxHeight(d);
//                            isLoad = true;
                            isLoad.set(true);
                        }
                    }
                }
        );

        webView.getEngine().setCreatePopupHandler(new Callback<PopupFeatures, WebEngine>() {

            @Override
            public WebEngine call(PopupFeatures p) {
                Stage stage = new Stage(StageStyle.UTILITY);
                WebView wv2 = new WebView();
                stage.setScene(new Scene(wv2));
                stage.show();
                return wv2.getEngine();
            }
        });

        webView.focusedProperty().addListener((InvalidationListener)l->{
            if (!webView.focusedProperty().get()) {
                try{
                    webView.getEngine().executeScript("cleanSelection()");
                } catch (Exception e) {}
            }
        });
        this.focusedProperty().addListener(e->webView.requestFocus());
    }

    private ImTextArea createImTextArea(DbMessage textMessage) {
        ImTextArea imTextArea = new ImTextArea();
        imTextArea.setImData(textMessage.getContent());
        imTextArea.setEditable(false);
//        imTextArea.setAutoHeight(true);
        return imTextArea;
    }

    private void copyMessage(DbMessage message) {
        Clipboard clipboard = Clipboard.getSystemClipboard();
        ClipboardContent content = new ClipboardContent();
        content.putString(ImTextPane.COPY_HEADER + TextItem.SPLIT_STRING +  message.getContent() + TextItem.SPLIT_STRING);

        clipboard.setContent(content);
    }

    private Node createImagePane(DbMessage message) {
        StackPane stackPane = new StackPane();
        stackPane.getStyleClass().add("message-image");

        ImageView imageView = new ImageView();
        imageView.setMouseTransparent(true);
        TextField textField = new TextField();
        textField.setMaxWidth(1);
        stackPane.getChildren().addAll(textField, imageView);
        imageView.setFitWidth(300);
        imageView.setFitHeight(60);
        textField.setOnKeyPressed(e-> {
            if(e.isControlDown() && e.getCode() == KeyCode.C) {
                copyMessage(message);
            }
        });
        stackPane.setOnMousePressed(e-> {
            textField.requestFocus();
        });
        try {
            String img = message.getContent();
            if (img.startsWith(TextItem.SPLIT_STRING)) {
                img = ImageTextItem.parseUrl(img);
            }
            Image image = new Image(img);
            imageView.setImage(image);
            stackPane.setOnMouseClicked(e->{
                if (e.getClickCount() != 2) return;
                Stage stage = new Stage();
                RegionUtil.FxmlBean<VBox, ImagePageController> node = RegionUtil.loadFxmlBean(this.getClass().getResource("/fxmls/ImagePage.fxml"));
                node.getController().setImage(image);
                Scene scene = new Scene(node.getNode(), 800, 600);
                stage.setScene(scene);
                stage.show();
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stackPane;
    }
}
